package com.dyava.commons.lock.redis;

import com.dyava.commons.lock.KeyLockException;
import com.dyava.commons.lock.KeyLockPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

public class RedisKeyLockPool extends KeyLockPool {
    static Logger log = LoggerFactory.getLogger(RedisKeyLockPool.class);

    StringRedisTemplate stringRedisTemplate;

    public StringRedisTemplate getStringRedisTemplate() {
        return stringRedisTemplate;
    }

    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    /** 看门狗线程 */
    public ScheduledExecutorService threadPoolWatchDog = Executors.newScheduledThreadPool(1,(r) ->new Thread(r,"thread-keylock-redis"));
    /**
     * 本线程上的锁定栈
     */
    ThreadLocal<LinkedList<RedisKeyLock>> threadLocalRegisterHolderList = new ThreadLocal<LinkedList<RedisKeyLock>>();

    public ScheduledExecutorService getThreadPoolWatchDog() {
        return threadPoolWatchDog;
    }

    LinkedList<RedisKeyLock>  getHolderList(){
        LinkedList<RedisKeyLock>  list = threadLocalRegisterHolderList.get();
        if(list==null){
            list = new LinkedList<>();
            threadLocalRegisterHolderList.set(list);
        }
        return list;
    }


    void unregisterHolder(RedisKeyLock lock){
        LinkedList<RedisKeyLock>  list = getHolderList();
        Iterator<RedisKeyLock> ite = list.iterator();
        while(ite.hasNext()){
            if(ite.next() == lock){
                list.pollLast();
            }
        }
        if(list.isEmpty()){
            threadLocalRegisterHolderList.remove();
        }
    }
    void registerHolder(RedisKeyLock lock){
        LinkedList<RedisKeyLock>  list = getHolderList();
        list.add(lock);
    }

    /**
     * 此key是否已经被本线程的人锁住
     * @param lock
     * @return
     */
    boolean isExistLockedKey(RedisKeyLock lock){
        LinkedList<RedisKeyLock> list = getHolderList();
        for(RedisKeyLock old : list){
            if(old==lock){
                throw new KeyLockException("不可重复lock");
            }
            if(old.getKey().equals(lock.getKey())){
                return true;
            }
        }
        return false;
    }

    @Override
    public RedisKeyLock createLock(String lockKey){
        RedisKeyLock lock = new RedisKeyLock(this,lockKey);
        return lock;
    }


}
